// ==UserScript==
// @name         Economist 经济学人免费看，全部解锁，并移除了广告
// @namespace    economist_hack
// @version      1.0.3
// @description  由于油叉上破解经济学人网站上的脚本很少有继续更新的，为了能继续白嫖经济学人，我在原作者@ Chaio Zhao 的基础上做了一点增减以及小优化，不定时会更新。如果感觉这个插件有用的话，可以点一个小小的赞哦👍
// @author       https://github.com/kunieone
// @match        https://*.economist.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @grant        none
// @license      MIT
// @esversion    6
// @downloadURL
// @updateURL
// ==/UserScript==

(function() {
    'use strict';

    // --- Helper Functions ---
    function addContent(jsonData) {
        let contentParagraph = "";
        for (let ii = 0; ii < jsonData.length; ii++) {
            const item = jsonData[ii];
            switch (item.type) {
                case "text":
                    contentParagraph += item.data;
                    break;
                case "tag": {
                    let attr = "";
                    if (item.attribs) {
                        for (const key in item.attribs) {
                            if (item.attribs.hasOwnProperty(key)) {
                                attr += " " + key + '="' + item.attribs[key] + '"';
                            }
                        }
                    }
                    contentParagraph += `<${item.name}${attr}>${addContent(item.children)}</${item.name}>`;
                    break;
                }
                default:
                    contentParagraph += "<u>" + JSON.stringify(item) + "</u>";
                    break;
            }
        }
        return contentParagraph;
    }

    // --- Ad Blocker ---
    (function adBlocker() {
        // Override XMLHttpRequest to block requests to pips.taboola.com (more efficient)
        const originalXHR = window.XMLHttpRequest;
        window.XMLHttpRequest = function() {
            const instance = new originalXHR();
            instance.open = function(method, url) {
                const blockedURL = 'blocked.pips.taboola.com';
                if (typeof url === 'string') {
                    url = url.replace(/pips\.taboola\.com/g, blockedURL);
                }
                originalXHR.prototype.open.apply(this, arguments);
            };
            return instance;
        };
    })();

    // --- Cleaner ---
  (function cleaner() {
    const adSelectors = [
        ".layout-sticky-rail-advert-wrapper",
        "#AdBillboard",
        "#gpt-ad-slot-right-rail-r0",
        "#gpt-ad-slot-regwall",
        ".newsletter-signup",
        "#_evidon_banner",
        `[class^="adComp"]`,
        `div[class*="adComponent_advert"]`,
        `div[class*="adComponent"]`,
        `[class*="expandable-banner"]`,
        "[ng-show]",
        "div.wall-overlay",
        "div.paywall.css-6lg4nz.etbj8gd0",
        "div.expandable-banner",
        "div.expandable-banner__header"
    ];

    console.log("Removing ads...");

    // 合并选择器，一次删除。
    function removeAds() {
        const combinedSelector = adSelectors.join(", ");
        $(combinedSelector).remove();
        console.log("Ads removed.");
    }

    // 初始广告清除，快速运行一次
    removeAds();

    // MutationObserver 观察动态添加的元素
    const observer = new MutationObserver(function(mutations) {
        removeAds(); // 发生变化时调用 removeAds
        console.log("MutationObserver triggered, ads removed.");
    });

    // 开始观察body的变化
    observer.observe(document.body, {
        childList: true,    // 监控子元素的直接添加/删除
        subtree: true       // 扩展到所有后代元素
    });

    // 设置一个删除广告的时间间隔作为备用
    const adRemovalInterval = setInterval(removeAds, 5000);

})();


    // --- Cracker ---
    (function cracker() {
        function crackArticle() {
            console.log("#{debugdebug} Cracking article...");

            const postQuery = "#content p.article__body-text";
            const nextData = $("#__NEXT_DATA__");
            const contentParent = "[data-body-id]>div";

            const addContentTimer = setInterval(() => {
                if ($(postQuery).length <= 2) {
                    $(postQuery).remove();
                    $("[data-body-id]>div>div:nth-child(0)").remove();
                    $("[data-body-id]>div>div:nth-child(1)").remove();
                    $(".layout-article-regwall").remove();

                    if (nextData.length) {
                        try {
                            const rawData = JSON.parse(nextData[0].textContent);
                            const contentData = rawData?.props?.pageProps?.content?.text;

                            if (Array.isArray(contentData)) {
                                let contentParagraph = "";
                                let figureFlag = false;

                                for (const item of contentData) {
                                    if (item.type === "tag") {
                                        switch (item.name) {
                                            case "p": {
                                                contentParagraph += `<p class="article__body-text">${addContent(item.children)}</p>`;
                                                break;
                                            }
                                            case "figure": {
                                                if (item.attribs?.itemtype === "https://schema.org/ImageObject") {
                                                    for (const childItem of item.children) {
                                                        if (childItem.name === "img") {
                                                            if (figureFlag) {
                                                                contentParagraph += "</div>";
                                                                figureFlag = false;
                                                            }
                                                            contentParagraph += `<div class="article__body-text-image"><figure><div><img src="${childItem.attribs.src}"></div></figure>`;
                                                            figureFlag = true;
                                                        }
                                                    }
                                                }
                                                break;
                                            }
                                            case "h2": {
                                                contentParagraph += `<h2>${addContent(item.children)}</h2>`;
                                                break;
                                            }
                                            default: {
                                                contentParagraph += `<${item.name}>${addContent(item.children)}</${item.name}>`;
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (figureFlag) {
                                    contentParagraph += "</div>";
                                }

                                $(contentParent).append(contentParagraph);
                            } else {
                                console.log("Content data is not an array.");
                            }
                        } catch (error) {
                            console.error("Error parsing JSON:", error);
                        }
                    }

                    clearInterval(addContentTimer);
                    console.log("Article cracked.");
                }
            }, 300);
        }

        let found = false;
        let interval = setInterval(() => {
            const element = document.querySelector("#tp-regwall");
            if (element) {
                console.log("Found regwall.");
                found = true;
                setTimeout(crackArticle, 0);
                clearInterval(interval);
            } else {
                console.log("Regwall not found.");
            }
        }, 1000); // Check every 1 seconds

        setTimeout(() => {
            if (!found) {
                clearInterval(interval);
                console.warn("#{debugdebug} Regwall not found within 30 seconds.");
            }
        }, 30000);
    })();
})();
